home *** CD-ROM | disk | FTP | other *** search
/ Amiga Inside! / Amiga FD Inside (1995)(Ultramax).iso / berndspd / devtools / precognition / src / library / listbrowser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-16  |  14.1 KB  |  521 lines

  1. /* ==========================================================================
  2. **
  3. **                         ListBrowser.c
  4. **
  5. ** ©1991 WILLISoft
  6. **
  7. ** ==========================================================================
  8. */
  9.  
  10. #include <string.h>
  11. #include "minmax.h"
  12. #include "ListBrowser.h"
  13. #include "ListBrowserClass.h"
  14. #include "EmbossedGadgetClass.h"
  15. #include "precognition.h"
  16. #ifndef __GNUC__
  17. #include <clib/exec_protos.h>
  18. #include <clib/intuition_protos.h>
  19. #include <clib/graphics_protos.h>
  20. #include <clib/diskfont_protos.h>
  21. #endif
  22. #ifdef __GNUC__
  23. #include <proto/exec.h>
  24. #include <proto/intuition.h>
  25. #include <proto/graphics.h>
  26. #include <proto/diskfont.h>
  27. #endif
  28. #ifdef __SASC
  29. #include <proto/exec.h>
  30. #include <proto/intuition.h>
  31. #include <proto/graphics.h>
  32. #include <proto/diskfont.h>
  33. #endif
  34.  
  35. #include "amigamem.h"
  36. /* Additions for prototypes -- EDB */
  37. #include "Intuition_utils.h"
  38.  
  39. #define CHAR_WIDTH  8   /* Width  of Topaz 80 font.*/
  40. #define CHAR_HEIGHT 9   /* Height of Topaz 80 font.*/
  41. #define BROWSER_ENTRY_HEIGHT (CHAR_HEIGHT + 1)
  42. #define BORDER_WIDTH 3
  43. #define BASELINE     8
  44.  
  45. #define isSelected(q) ( q & ENTRY_SELECTED )
  46.  
  47. const StringList *ListBrowser_StringList_of( ListBrowser *self )
  48. {
  49.    return &self->List;
  50. }
  51.  
  52. void ListBrowser_Init( ListBrowser   *self,
  53.                        PIXELS         LeftEdge,
  54.                        PIXELS         TopEdge,
  55.                        PIXELS         Width,
  56.                        PIXELS         Height,
  57.                        pcg_3DPens     Pens,
  58.                        BOOL           SelectMany )
  59. {
  60.  
  61.    EmbossedGadget_Init( &self->eg, LeftEdge, TopEdge, 0, 0,
  62.       GADGHNONE, RELVERIFY, BOOLGADGET, Pens, NULL );
  63.  
  64.    self->eg.isa       = ListBrowserClass();
  65.    self->SelectMany   = SelectMany;
  66.    self->YOffset      = 0;
  67.    SetLocation( (GraphicObject *)self, LeftEdge, TopEdge );
  68.    SetSize( (GraphicObject *)self, Width, Height );
  69.  
  70.    /* Initialize List structure... */
  71.    StringList_Init( &self->List, TRUE );
  72.  
  73. }
  74.  
  75. void ListBrowser_CleanUp( ListBrowser *self )
  76. {
  77.  
  78.  
  79.    StringList_CleanUp( StringList_of( (StringLister *)self ) );
  80.    EmbossedGadget_CleanUp( (EmbossedGadget *)self );
  81. }
  82.  
  83. Point ListBrowser_AskSize( ListBrowser *self,
  84.                            PIXELS       Width,
  85.                            PIXELS       Height )
  86. {
  87.    Point size;
  88.    short nCols, nRows;
  89.  
  90.    nCols = ( Width - BORDER_WIDTH * 2  ) / CHAR_WIDTH;
  91.    nRows = ( Height - BORDER_WIDTH * 2 ) / BROWSER_ENTRY_HEIGHT;
  92.  
  93.    nCols = MAX( nCols, 5 );
  94.    nRows = MAX( nRows, 5 );
  95.  
  96.    size.x = nCols*CHAR_WIDTH           + BORDER_WIDTH*2;
  97.    size.y = nRows*BROWSER_ENTRY_HEIGHT + BORDER_WIDTH*2;
  98.  
  99.    return size;
  100. }
  101.  
  102.  
  103. Point ListBrowser_SetSize( ListBrowser *self,
  104.                             PIXELS       Width,
  105.                             PIXELS       Height )
  106. {
  107.    Point size;
  108.  
  109.    size = AskSize( (GraphicObject *)self, Width, Height );
  110.  
  111.    Forbid(); /* Don't want Intuition looking at these while we modify em. */
  112.    self->eg.Size     = size;
  113.    self->eg.g.Width  = size.x - BORDER_WIDTH*2;
  114.    self->eg.g.Height = size.y - BORDER_WIDTH*2;
  115.  
  116.    pcg_Init3DBox(  self->eg.BoxBorder,
  117.                    -BORDER_WIDTH, -BORDER_WIDTH,
  118.                    size.x, size.y,
  119.                    self->eg.Pens.BrightPen,  self->eg.Pens.DarkPen,
  120.                    self->eg.BoxBorder->BottomRight.NextBorder );
  121.    Permit();
  122.  
  123.  
  124.    self->nColumns = ( size.x - BORDER_WIDTH * 2 ) / CHAR_WIDTH;
  125.    self->nRows    = ( size.y - BORDER_WIDTH * 2 ) / BROWSER_ENTRY_HEIGHT;
  126.  
  127.    /* EDB --  reset Yoffset to zero when resized */
  128.    /* doesn't seem to fix the bug I wanted to fix -- EDB */
  129.    /*   ListBrowser_SetYOffset( self, 0 ); */
  130.    return size;
  131. }
  132.  
  133. Point ListBrowser_SetLocation( ListBrowser *self,
  134.                                PIXELS       LeftEdge,
  135.                                PIXELS       TopEdge )
  136. {
  137.    Point location;
  138.  
  139.    Forbid();
  140.    self->eg.Location.x = LeftEdge;
  141.    self->eg.Location.y = TopEdge;
  142.    self->eg.g.LeftEdge = LeftEdge + BORDER_WIDTH;
  143.    self->eg.g.TopEdge  = TopEdge  + BORDER_WIDTH;
  144.    Permit();
  145.  
  146.  
  147.    return location;
  148. }
  149.  
  150. USHORT ListBrowser_SetYOffset( ListBrowser *self,
  151.                                USHORT       YOffset )
  152. {
  153.    SHORT MaxY;
  154.  
  155.    MaxY          = MAX( self->List.nEntries-self->nRows, 0 );
  156.    self->YOffset = MIN( YOffset, MaxY );
  157.  
  158.    return self->YOffset;
  159. }
  160.  
  161.  
  162.  
  163. #define DESELECT_ALL(b) ListBrowser_SelectAll( b, FALSE )
  164.  
  165. void ListBrowser_SelectAll( ListBrowser *self, BOOL Select )
  166. /* Selects or deselects everything in the list. */
  167. {
  168.    USHORT i;
  169.  
  170.    for( i = 0; i < self->List.nEntries; i++ )
  171.    {
  172.       if( Select )
  173.          self->List.Qualifiers[i] |= ENTRY_SELECTED;
  174.       else
  175.          self->List.Qualifiers[i] &= (UBYTE) ~ENTRY_SELECTED;
  176.    }
  177.  
  178. }
  179.  
  180. void ListBrowser_SelectString( ListBrowser  *self,
  181.                                USHORT        i,
  182.                                BOOL          Select   )
  183. {
  184.    if( ( ! self->SelectMany ) && ( Select ) )
  185.       DESELECT_ALL( self );
  186.  
  187.    if( Select )
  188.       self->List.Qualifiers[i] |= ENTRY_SELECTED;
  189.    else
  190.       self->List.Qualifiers[i] &= ~ENTRY_SELECTED;
  191. }
  192.  
  193. void ListBrowser_DrawEntry( ListBrowser    *self,
  194.                             RastPort       *RPort,
  195.                             USHORT          index )
  196. {
  197.    USHORT count, X, Y, Xend, Yend;
  198.    UBYTE qual, succ, pred;
  199.    char **Entries;
  200.    UBYTE *Qualifiers;
  201.    pcg_3DPens pens;
  202.  
  203.    /* Additions for correct font behavior under 2.x/3.x Amiga OS*/
  204.  
  205. /*   TextAttr pcg_Topaz80 =
  206.    { "topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT };  */
  207.  
  208.    struct TextFont *myfont, *oldfont;
  209.  
  210.    Entries    = self->List.Entries;
  211.    Qualifiers = self->List.Qualifiers;
  212.  
  213.    X      = self->eg.Location.x + BORDER_WIDTH;
  214.    Y      = self->eg.Location.y + BORDER_WIDTH
  215.             + (index-self->YOffset) * BROWSER_ENTRY_HEIGHT;
  216.    Xend   = X + self->eg.g.Width-1;
  217.    Yend   = Y + BROWSER_ENTRY_HEIGHT;
  218.    pens   = self->eg.Pens;
  219.  
  220.    SetDrMd( RPort, JAM1 );
  221.    /* Clear the entry. */
  222.    SetAPen( RPort, pens.BackPen );
  223.    RectFill( RPort, X, Y, Xend, Yend );
  224.  
  225.  
  226.    qual = Qualifiers[index];
  227.    if( index )
  228.       pred = Qualifiers[index-1];
  229.    else
  230.       pred = 0;
  231.  
  232.    if( index +1 < self->List.nEntries )
  233.       succ = Qualifiers[index+1];
  234.    else
  235.       succ = 0;
  236.  
  237.  
  238.    if( qual & ENTRY_SPECIAL )
  239.       SetAPen( RPort, pens.FrontPen+1 );
  240.    else
  241.       SetAPen( RPort, pens.FrontPen );
  242.  
  243.    Move( RPort, X+1, Y+BASELINE );
  244.    count = strlen( Entries[index] );
  245.    count = MIN( self->nColumns, count );
  246.  
  247.    /* Under 2.x/3.x AmigaDOS we cannot presume that topaz80 is the default
  248.     * font, so we open it for our use, and close it when done.
  249.     * - EDB
  250.     */
  251.  
  252. if( myfont = OpenDiskFont( DefaultFont( (GraphicObject *)self ) /* &pcg_Topaz80 */ ) )
  253.   {
  254.      oldfont = RPort->Font;
  255.      SetFont( RPort, myfont );
  256.    Text( RPort, Entries[index], count );
  257.      SetFont( RPort, oldfont );
  258.      CloseFont( myfont );
  259.   }
  260.  
  261.  
  262.    if( isSelected( qual ) )
  263.    {
  264.       SetDrMd( RPort, COMPLEMENT );
  265.  
  266.       /* Draw 3D lines. */
  267.       RectFill( RPort, X, Y, Xend, Yend );
  268.       SetDrMd(  RPort, JAM1 );
  269.       SetAPen( RPort, pens.DarkPen );
  270.       Move( RPort, X, Yend );
  271.       Draw( RPort, X, Y );
  272.  
  273.       SetAPen( RPort, pens.BrightPen ); /* Right side bar. */
  274.       Move( RPort, Xend, Y );
  275.       Draw( RPort, Xend, Yend );
  276.    }
  277.  
  278.    /* Draw top bar. */
  279.    if( ( ( !isSelected( pred ) ) && isSelected( qual ) ) )
  280.          /* previous is not selected, entry is  */
  281.    {
  282.       SetAPen( RPort, pens.DarkPen );
  283.       Move( RPort, X,    Y );
  284.       Draw( RPort, Xend, Y );
  285.    }
  286.    else if( isSelected( pred ) && ( !isSelected( qual ) ) )
  287.       /* previous is selected, entry is not */
  288.    {
  289.       SetAPen( RPort, pens.BrightPen );
  290.       Move( RPort, X,    Y );
  291.       Draw( RPort, Xend, Y );
  292.    }
  293.  
  294.    /* Draw bottom bar */
  295.    if( ( !isSelected( succ ) ) && isSelected( qual ) )
  296.       /* successor is not selected, entry is  */
  297.    {
  298.       SetAPen( RPort, pens.BrightPen );
  299.       Move( RPort, X,    Yend );
  300.       Draw( RPort, Xend, Yend );
  301.    }
  302.    else if( isSelected( succ ) && ( !isSelected( qual ) ) )
  303.       /* successor is selected, entry is not */
  304.    {
  305.       SetAPen( RPort, pens.DarkPen );
  306.       Move( RPort, X,    Yend );
  307.       Draw( RPort, Xend, Yend );
  308.    }
  309. }
  310.  
  311.  
  312. void ListBrowser_Render( ListBrowser *self,
  313.                          RastPort    *RPort )
  314. {
  315.    USHORT        X, Y, Xend, Yend;
  316.    USHORT        i, j;
  317.  
  318.    X      = self->eg.g.LeftEdge;/* + BORDER_WIDTH;*/
  319.    Y      = self->eg.g.TopEdge; /*  + BORDER_WIDTH;*/
  320.    Xend   = X + self->eg.g.Width-1;
  321.    Yend   = Y + self->eg.g.Height-1;
  322.  
  323.  
  324.    DrawBorder( RPort, (struct Border *)self->eg.BoxBorder, self->eg.g.LeftEdge, self->eg.g.TopEdge );
  325.  
  326.    /* Clear the display area. */
  327.    SetDrMd( RPort, JAM1 );
  328.    SetAPen( RPort, self->eg.Pens.BackPen );
  329.    RectFill( RPort, X, Y, Xend, Yend );
  330.  
  331.  
  332.    /* Display the list */
  333.    for( j = 0, i = self->YOffset; j < self->nRows; j++, i++)
  334.    {
  335.       if( i >= self->List.nEntries ) break;
  336.       ListBrowser_DrawEntry( self, RPort, i );
  337.    }
  338. }
  339.  
  340.  
  341. void ListBrowser_ChangeHighlight( ListBrowser *self,
  342.                                   USHORT       new_highlighted_entry, /* index */
  343.                                   RastPort    *RPort )
  344. {
  345.    USHORT        i, j;
  346.    UBYTE  *Qualifiers;
  347.  
  348.  
  349.    /* Display the list */
  350.    Qualifiers = self->List.Qualifiers;
  351.  
  352.    /* Deselect the old one. */
  353.    i = self->YOffset;
  354.    for( j = 0; j < self->nRows; j++, i++ )
  355.    {
  356.       if( i >= self->List.nEntries ) break;
  357.  
  358.       if( isSelected( Qualifiers[i] ) )
  359.       {
  360.          /* If this is the old highlight */
  361.          Qualifiers[i] &= ~ENTRY_SELECTED;
  362.          ListBrowser_DrawEntry( self, RPort, i );
  363.       }
  364.    }
  365.  
  366.    Qualifiers[new_highlighted_entry] |= ENTRY_SELECTED;
  367.  
  368.    if( ( new_highlighted_entry - self->YOffset >= 0 ) &&
  369.        ( new_highlighted_entry - self->YOffset < self->nRows ) )
  370.       ListBrowser_DrawEntry( self, RPort, new_highlighted_entry );
  371.  
  372. }
  373.  
  374.                          /* Changed from ListBrowser * */
  375. void ListBrowser_Refresh( Interactor *self )
  376. {
  377.    struct pcgWindow *window;
  378.  
  379.    window = InteractorWindow( (Interactor *)self );
  380.    Render( (GraphicObject *)self, window->Window->RPort );
  381. }
  382.  
  383.  
  384. /* Changed from void -- EDB */
  385. BOOL ListBrowser_AddString( ListBrowser    *self,
  386.                             char           *entry,
  387.                             UBYTE           qualifier )
  388. {
  389.    if( ( ! self->SelectMany ) && isSelected( qualifier ) )
  390.       DESELECT_ALL( self );
  391.       /* This new entry is selected, so all others must be deselected. */
  392.    /* added return -- EDB */
  393.    return( StringList_AddString( &self->List, entry, qualifier ) );
  394. }
  395.  
  396.  
  397. BOOL ListBrowser_DeleteString( ListBrowser *self, USHORT i )
  398. {
  399.    BOOL result;
  400.    StringList *sl;
  401.  
  402. /*DUMPWAIT("ListBrowser_DeleteString\n");*/
  403.  
  404.    sl = StringList_of( (StringLister *)self );
  405.  
  406.    result = StringList_DeleteString( sl, i );
  407.  
  408.    ListBrowser_SetYOffset( self, self->YOffset );
  409.  
  410. /*DUMPWAIT("end ListBrowser_DeleteString\n");*/
  411.  
  412.    return result;
  413.  
  414. }
  415.  
  416. BOOL ListBrowser_DeleteAllStrings( ListBrowser *self )
  417. {
  418.    BOOL result;
  419.  
  420.    result = StringList_DeleteAllStrings( &self->List );
  421.    ListBrowser_SetYOffset( self, self->YOffset );
  422.  
  423.    return result;
  424. }
  425.  
  426.  
  427.  
  428. #define CLAIM_EVENT(b,e) ( &b->eg.g == (Gadget *)e->IAddress )
  429.  
  430. USHORT ListBrowser_Respond( ListBrowser  *self,
  431.                             IntuiMessage *Event )
  432. {
  433.    Point        Mouse;
  434.    USHORT       entry_no;
  435.    USHORT       response = 0;
  436.    UBYTE        qual;
  437.  
  438.    switch( Event->Class )
  439.    {
  440.       case REFRESHWINDOW:
  441.          ListBrowser_Render( self, Event->IDCMPWindow->RPort );
  442.          response = RESPONDED;
  443.          break;
  444.  
  445.       case GADGETUP:
  446.          if( CLAIM_EVENT( self, Event ) )
  447.          {
  448.             /* Translate into Gadget-Relative Coordinates. */
  449.             GadgetRelativeCoords( &self->eg.g, Event, &Mouse );
  450.             entry_no = ( Mouse.y - BORDER_WIDTH ) / BROWSER_ENTRY_HEIGHT
  451.                         + self->YOffset;
  452.             entry_no = MAX( entry_no, 0 );
  453.  
  454.             qual = self->List.Qualifiers[entry_no];
  455.  
  456.             if( entry_no < self->List.nEntries )
  457.             {
  458.                if( self->SelectMany )
  459.                {
  460.                   SelectString( (StringLister *)self, entry_no, !isSelected( qual ) );
  461.                   ListBrowser_DrawEntry( self,
  462.                      Event->IDCMPWindow->RPort, entry_no );
  463.                }
  464.                else
  465.                {
  466.                   if( !isSelected( qual ) ) /* Only select if not already.  */
  467.                   {                         /* (Avoids ugly screen update.) */
  468.                      ListBrowser_ChangeHighlight( self, entry_no,
  469.                            Event->IDCMPWindow->RPort );
  470.                   }
  471.                }
  472.             }
  473.             response = RESPONDED | CHANGED_STATE | CONSUMED_EVENT;
  474.          }
  475.          break;
  476.  
  477.    }
  478.    return response;
  479. }
  480.  
  481.  
  482.  
  483. BOOL ListBrowser_elaborated = FALSE;
  484.  
  485. struct StringListerClass ListBrowser_Class;
  486.  
  487. void ListBrowserClass_Init( struct StringListerClass *class )
  488. {
  489.  
  490.    StringListerClass_Init( class );
  491.    EmbossedGadgetClass_Init( (struct InteractorClass *)class );
  492.    class->isa         = StringListerClass();
  493.    class->ClassName   = "ListBrowser";
  494.    class->CleanUp     = (void(*)(PObject *))ListBrowser_CleanUp;
  495.    class->AskSize     = (Point(*)(GraphicObject *, PIXELS, PIXELS))ListBrowser_AskSize;
  496.    class->SetSize     = (Point(*)(GraphicObject *, PIXELS, PIXELS))ListBrowser_SetSize;
  497.    class->SizeFlags   = GraphicObject_SizeFlagsAll;
  498.    class->SetLocation = (Point(*)(GraphicObject *, PIXELS, PIXELS))ListBrowser_SetLocation;
  499.    class->Respond     = (USHORT(*)(Interactor *, IntuiMessage *))ListBrowser_Respond;
  500.    class->Render      = (void(*)(GraphicObject *, RastPort *))ListBrowser_Render;
  501.    class->Refresh     = (void(*)(Interactor *))ListBrowser_Refresh;
  502.  
  503.    class->AddString     = (BOOL(*)(StringLister *, char *, UBYTE))ListBrowser_AddString;
  504.    class->DeleteString  = (BOOL(*)(StringLister *, USHORT))ListBrowser_DeleteString;
  505.    class->DeleteAllStrings  = (BOOL(*)(StringLister *))ListBrowser_DeleteAllStrings;
  506.    class->StringList_of = (StringList*(*)(StringLister *))ListBrowser_StringList_of;
  507.    class->SelectString  = (void(*)(StringLister *, USHORT, BOOL))ListBrowser_SelectString;
  508. }
  509.  
  510.  
  511. struct StringListerClass *ListBrowserClass( void )
  512. {
  513.    if( ! ListBrowser_elaborated )
  514.    {
  515.       ListBrowserClass_Init( &ListBrowser_Class );
  516.       ListBrowser_elaborated = TRUE;
  517.    }
  518.  
  519.    return &ListBrowser_Class;
  520. }
  521.